package com.cksys.achievement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cksys.achievement.entity.*;
import com.cksys.achievement.enums.RegisterEnum;
import com.cksys.achievement.enums.Roles;
import com.cksys.achievement.enums.SexEnum;
import com.cksys.achievement.mapper.RoleMapper;
import com.cksys.achievement.mapper.UserMapper;
import com.cksys.achievement.mapper.UserRoleMapper;
import com.cksys.achievement.service.IResultPictureService;
import com.cksys.achievement.service.IResultService;
import com.cksys.achievement.service.IResultUserService;
import com.cksys.achievement.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cksys.achievement.utils.RestResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tadechen
 * @since 2019-09-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserRoleMapper userRoleMapper;

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    IResultService resultService;

    @Autowired
    IResultUserService resultUserService;

    @Autowired
    IResultPictureService resultPictureService;

    @Override
    public List<User> getUsersByUserNames(String[] usernames) {
        ArrayList<User> users = new ArrayList<>();
        for (String username : usernames) {
            User user = this.getByUserName(username);
            users.add(user);
        }
        return users;
    }

    @Override
    public List<User> getUsersByRealNames(String[] realNames) {
        ArrayList<User> users = new ArrayList<>();
        for (String realName : realNames) {
            User user = this.getByRealName(realName);
            users.add(user);
        }
        return users;
    }

    @Override
    public User getByUserName(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    public User getByRealName(String realName) {
        return userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getRealName, realName));
    }

    @Override
    public Boolean isExist(Integer id) {
        return userMapper.selectById(id) != null;
    }

    @Override
    public IPage<User> searchUser(IPage<User> page, String username, String realName, SexEnum sexEnum, Roles roles, RegisterEnum registerEnum) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (username != null && !"".equals(username)) {
            queryWrapper.like(User::getUsername, username);
        }
        if (realName != null && !"".equals(realName)) {
            queryWrapper.like(User::getRealName, realName);
        }
        if (sexEnum != null) {
            queryWrapper.eq(User::getSex, sexEnum);
        }
        if (registerEnum != null) {
            queryWrapper.eq(User::getRegister, registerEnum);
        }
        queryWrapper.orderByAsc(User::getRealName);
        queryWrapper.select(User::getUsername, User::getId, User::getRealName, User::getAvatarPath,
                User::getRegister, User::getSex, User::getAccountId,
                User::getEmail, User::getSalt, User::getToken);
        if (roles != null) {
            Integer rId = roleMapper.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getName, roles.getRoleName())).getId();
            List<Object> uIds = userRoleMapper.selectObjs(new LambdaQueryWrapper<UserRole>().eq(UserRole::getRoleId, rId).select(UserRole::getUserId));

            if (uIds.size() == 0) {
                return new Page<>(0, 0);
            } else {
                queryWrapper.in(User::getId, uIds);
                return userMapper.selectPage(page, queryWrapper);
            }
        } else {
            return userMapper.selectPage(page, queryWrapper);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean removeUser(Integer id) {
        UserRole userRole = userRoleMapper.selectOne(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
        if (!userRole.getRoleId().equals(1)) {
            return false;
        }
        boolean b = this.removeById(id);
        if (b) {
            List<ResultUser> resultUserList = resultUserService.list(new LambdaQueryWrapper<ResultUser>().eq(ResultUser::getUId, id));
            List<Integer> isLeaderRids = resultUserList.stream().filter(ResultUser::getIsLeader).map(ResultUser::getRId).collect(Collectors.toList());
            List<Integer> isNotLeaderRids = resultUserList.stream().filter(t -> !t.getIsLeader()).map(ResultUser::getRId).collect(Collectors.toList());

            if (isLeaderRids.size() > 0) {
                resultService.removeByIds(isLeaderRids);
                resultPictureService.remove(new LambdaQueryWrapper<ResultPicture>().in(ResultPicture::getRId, isLeaderRids));
                resultUserService.remove(new LambdaQueryWrapper<ResultUser>().in(ResultUser::getRId, isLeaderRids));
            }
            if (isNotLeaderRids.size() > 0) {
                resultUserService.remove(new LambdaQueryWrapper<ResultUser>().in(ResultUser::getRId, isNotLeaderRids).eq(ResultUser::getUId, id));
            }
            userRoleMapper.delete(new LambdaQueryWrapper<UserRole>().eq(UserRole::getUserId, id));
            return true;
        } else {
            throw new RuntimeException("删除用户失败!");
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean removeUsers(List<Integer> id) {
        boolean b = true;
        for (Integer t : id) {
            b = this.removeUser(t);
        }
        return b;
    }
}
